public class Main {
    public static void main(String[] args) {
        // ***** HTTP 协议 ****
        // HTTP 是一个应用层协议
        // 目前使用最大规模的版本是 HTTP 1.1
        // 使用HTTP 的场景:
        // 1. 浏览器打开网站 (基本上)
        // 2. 手机APP访问对应的服务器 (大概率)

        // 学习HTTP协议 重点还是学习 HTTP的报文格式
        // HTTP的报文格式 要分两部分来看待
        // 请求
        // 响应
        // HTTP协议 是 "一问一答" 结构模型的协议
        // 请求和响应的协议格式 是有所差异的
        // 有 : 一问一答 (访问网站)
        // 多问一答 (上传文件)
        // 一问多答 (下载文件)
        // 多问多答 (串流 / 远程桌面)

        // 呢么如何查看到HTTP请求和响应的格式呢?
        // 要用到一个工具 抓包工具 (这个东西 其实就是把网卡上经过的数据获取到并显示出来)
        // (这个是分析调试程序的重要手段) 如 wireshark (功能非常强大, 使用起来也比较复杂)
        //  使用 Fiddler 工具 (这是一个专门抓HTTP的抓包工具)
        // (虽然功能不强 但是使用起来简单方便)
        // 需要下载 Fiddler
        // 打开 Fiddler 之后
        // 是一个左右结构的程序. 左侧有一个列表, 列出了抓到的包有哪些. 右侧则是包的详情. 点击某个包
        // 右侧上方 是 请求 详情 ; 右侧下方 是响应详情
        // 新安装的fiddler 需要手动开启 HTTPS功能, 并且安装证书
        // (否则 只能抓 http)
        // 目前的互联网 环境上主要是 https
        // 如何开启呢 ? 打开 fiddler 之后 点击 Tools 选项 找到 Options , 点击里面的HTTPS选项 ,把里面的 勾 全打上
        // 然后会出现一个框, 问你是否要安装证书, 一定要选择"同意", 不选同意装不了

        // fiddler 抓的不只是浏览器,只要是 电脑上的某个应用程序访问了 http 也能够抓到

        // 但是 fiddler 还有例外情况 :
        // Fiddler 本质上是一个 "代理" , 可能会和其他的代理软件冲突~~, 什么是代理: 有件事 你需要做, 但是又不想亲自做, 就可以指挥别人来做~~
        // [代理客户端的称作 正向代理 , 代理 服务器端的称作 反向代理, fiddler 就是正向代理]
        // 在上述代理的过程中, 代理程序就可以获取到请求和响应的详细内容了
        //  除了fiddler 之外, 有的程序也是代理. 如: 加速器, vpn ...
        // 代理程序之间是冲突的 , 这样 fiddler 是由可能出问题的
        // 在不能抓包的情况下,一定要检查关闭之前的代理软件(也可能是一个浏览器插件)

        // 关于 Fiddler 的实际使用
        // 在使用之前 如果之前的东西太多了,可以 把他们都删除了 ctrl+A + delete 键 (删除完之后也会出现新的包)
        // 这样就可以让我们看到我们想看的包
        // 以打开edge为例 来看看这个抓包过程
        // 以bing域名的都是刚才打开的所产生的请求
        // 别的我们不关注,我们只需要关注蓝色的就行了, 蓝色的表示 得到的响应是 HTML ,需要重点关注
        // 获取到的黑色的是一些普通数据 (具体是什么数据看程序员怎么写的了, 我们也不清楚)
        // 灰色的可以直接忽略

        // 点击蓝色的. 在右侧上方点击Raw标签就可以看到当前请求的原始情况了
        // 如果嫌小, 可以点击当前右下角的 View in Notepad选项来用记事本打开
        // 如果在记事本中还嫌小 可以在里面设置字体

        // 会发现 HTTP 协议是文本格式的协议!!(协议的内容都是字符串)
        // 在右侧下方点击Raw标签显示的是响应的原始情况
        // 用记事本打开, 里面会发现有二进制的数据
        //(主要是压缩后的)

        //HTTP 响应经常会被压缩. 压缩之后, 体积变小,传输的时候, 节省网络带宽
        // 但是压缩和解压缩是需要消耗额外的CPU和时间的 , 但是相比直接还是省带宽更好
        // 那么如何解决呢?
        // 这时候点击呢个黄色的一条(表示的是解压缩), 点过之后再用记事本打开就行了
        // 解压缩之后可以发现响应的数据是一个 html
        //浏览器上显示的网页 就是 html 往往都是浏览器先请求对应的服务器,从服务器这边拿到的 页面 数据(html)

        // 那么 请求和 响应 都是包含了四个部分

        // 请求:
        // 1.首行 (HTTP 请求的第一行. 有三个部分的信息, 三个部分用空格分割 1) GET,HTTP请求的方法"method"
        //    2) URL (很长的呢一串,空格结束,把这一段称作URL) , 表示 唯一资源定位符. 描述了一个资源在网络上的位置
        //     3)版本号 最后的呢个 HTTP1.1 表示版本)
        // 2. 请求头(header) (从首行往后 都成为 header)
        // 是一个键值对结构的数据(有很多键值对)
        // 每个键值对都是独占一行
        // 使用 : 和 空格来区分  (这里的键值对都是属于 "标准规定的")
        //  3,空行
        // 请求头结束标记
        // 4.正文(body)
        // 有的 HTTP请求有 有的 HTTP 请求没有

        // 响应:
        // 1. 首行 (分成三个部分  1) 表示版本号 HTTP1.1 , 2) 表示状态码 (如:200) 描述了请求的结果
        //      3) 状态码的描述 (OK) 表示是否成功)
        // 2. 响应头 (header)
        // 同样也是键值对结构 , 同样有多个键值对
        // 每个键值对独占一行
        // 使用 : 和 空格来区分  (这里的键值对都是属于 "标准规定的")
        //  3,空行
        // 响应头结束标记
        // 4.正文(body)
        // 正文这里的内容可能比较长 , 可能是多种格式
        // 如 HTML, CSS ,JS,JSON ,图片,字体,音频....

        // 请求和响应的差异最大的部分是在首行这里的


        // 接下来就看一下请求和响应具体的详细情况

        // 先看请求当中的 URL (URL 是计算机中非常重要的概念. 不仅仅是在HTTP中涉及到.)
        // (URL描述了某个资源在网络上的位置)

        // ***URL 基本格式***
        //平时我们俗称的 "网址" 其实就是说的 URL (Uniform Resource Locator 统一资源定位符).
        //互联网上的每个文件都有一个唯一的URL，它包含的信息指出文件的位置以及浏览器应该怎么处理它.

        // http://user:pass@www.example.jp:80/dir/index.html?uid=1#ch1

        // http协议方案名
        //user:pass 登录认证信息
        // www.example.jp:  表示一个服务器地址 (可以是一个IP地址 也可以是一个域名)
        // 80  服务器端口号 (有时候是可以省略的,相当于浏览器给了一个默认值)
        // /dir/index.html 带层次的文件路径 (描述了你要访问服务器的哪个资源) (虽然写法是一个看起来像"目录"的写法
        // 实际上在服务器中不一定是以目录的形式来存储资源的..)
        // uid=1 查询字符串 (是一种键值对结构的数据,是以 ? 开头的. 键值对之间使用&来分割 , 键和值之间使用 = 来分割
        // 一个 url中的query string里可以包含N个键值对. 甚至可能很长 (query string中的键值对都是程序员可以自己定义的,
        // 不像header 中是标准规定的) , query string 的作用就是相当于这次请求进行了一些补充说明. )
        // ch1 片段标识符 (这个东西不是很常见了), 就是表示有个网页内容比较长,就可以分成多个"片段",通过片段表示符,就可以完成页面内部的跳转
        // 对于 query string 来说, 如果 value 部分要包含一些特殊符号的时候 往往需要进行 urlencode 操作
        // 本质上是一种转义字符
        // 后面使用 url 的时候, 要记得针对 query string 的内容进行好urlencode工作,处理不好有些浏览器就会出错,可能会解析失败,导致请求无法正常进行

        // 一个具体的 URL:
        // https://v.bitedu.vip/personInf/student?userId=10000&classId=100
        // https : 协议方案名. 常见的有 http 和 https, 也有其他的类型. (例如访问 mysql 时用的jdbc:mysql )

        //  user:pass : 登陆信息. 现在的网站进行身份认证一般不再通过 URL 进行了. 一般都会省略

        // v.bitedu.vip : 服务器地址. 此处是一个 "域名", 域名会通过 DNS 系统解析成一个具体的 IP 地址.
        //(通过 ping 命令可以看到,v.bitedu.vip 的真实 IP 地址为118.24.113.28 )

        // 端口号: 上面的 URL 中端口号被省略了. 当端口号省略的时候, 浏览器会根据协议类型自动决定使用
        //哪个端口. 例如 http 协议默认使用 80 端口, https 协议默认使用 443 端口.

        // /personInf/student : 带层次的文件路径.

        // userId=10000&classId=100 : 查询字符串(query string). 本质是一个键值对结构. 键值对之间使
        //用 & 分隔. 键和值之间使用 = 分隔.

        // 片段标识: 此 URL 中省略了片段标识. 片段标识主要用于页面内跳转. (例如 Vue 官方文档:
        //https://cn.vuejs.org/v2/guide/#%E8%B5%B7%E6%AD%A5, 通过不同的片段标识跳转到文档的不同章节)

        // HTTP 是工作中最常用到的协议之一
        // 面试中最常考的内容
        // 应用场景: 1) 网页和后台服务器的交互 . 2) app和后台服务器的交互
        // 通过抓包就可以更好的理解协议格式了


        // ***认识 "方法" (method)***
        // 1.GET 方法
        // GET 是最常用的 HTTP 方法. 常用于获取服务器上的某个资源.
        //在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求.
        //另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求

        // 2.POST 方法
        // POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面 , 和上传文件的时候 ).
        // (演示上传文件的时候 此处演示的是上传头像, 经过 Fiddler 观察发现 上传头像的 body 比较长.
        // 其实body 就是图像的本体. 图片本身是二进制数据, 此处把图片放到 http 请求中, 往往要进行 base64转码)
        // (base64转码 就是针对二进制数据进行重新转码(转义), 确保编码之后的数据就是纯文本的数据(base64 是一个既能编码又能解码))
        // 通过 HTML 中的 form 标签可以构造 POST 请求, 或者使用 JavaScript 的 ajax 也可以构造 POST 请求.

        // 区别 : GET 请求 , 通常会把要传给服务器的数据, 加到 url 的 query string 中
        // POST 请求, 通常把要传给服务器的数据, 加到 body中
        // (这是一个习惯用法(不是硬性规定))
        // (蓝色字体是获取网页响应的 得到 html 响应)
        // 刚才最开始没有抓到返回页面的请求, 是因为命中了浏览器缓存 (浏览器显示的网页,其实是从服务器这边下载的 html.
        // html内容可能比较多, 体积可能比较大, 通过网络加载,消耗的时间就可能会比较多 .
        // 所以 浏览器一般都会自己带有缓存. 就会把之前加载过的页面,保存在本地硬盘上. 下次访问直接读取本地硬盘的数据即可)

        // 其实有很多http请求的形式 , 不只是上面的两个
        // 只不过上面的两个是最常见的 , 其他的基本上就用不到了
        // 这些HTTP请求, 最初心就是为了表示不同的"语义 "
        // 如 : OUT  HEAD DELETE OPTIONS TRACE CONNECT LINK UNLINK
        // 但是在实际的使用过程中, 初心 已经被遗忘了
        // HTTP 的各种请求 目前来说已经不一定完全遵守自己的初心了. 实际上程序员如何使用, 更加随意的

        // 平时 一般谈 GET 和 POST 的区别 (经典面试题)
        // 开篇:1. 直接说 GET 和 POST 没有本质区别 (双方可以替换对方的场景)
        // 2.虽然没有本质区别, 但是在使用习惯上 还是存在一些差异 ~~
        // 1) GET 请求 , 通常会把要传给服务器的数据, 加到 url 的 query string 中 ; POST 请求, 通常把要传给服务器的数据, 加到 body中
        // (这是使用习惯上最大的区别) , (但是上述的情况并不是绝对的
        // GET 也可以使用 body, POST 也可以使用 query string . 使用前提是 客户端/ 服务器都得按照一样的方式来处理代码 (所以我们一般并不这样用))
        // 2) 语义上的差异. (GET 和 POST还是比较明确的) GET大多数是用来获取数据 , POST大多数是用来提交数据 (登录 + 上传)
        // (GET 和 POST 之间的差别 , 有些说法 还是要注意的
        //  1 GET请求能传递的数据量有上限, POST 传递的数据量没有上限(这个说法是不科学的 这是一个历史遗留问题))
        // 2. GET请求传递数据不安全. POST 请求传递数据更安全 (依据是:
        // 如果使用GET请求来实现登录, 点击登录的时候,就会把用户名把密码放到 url中, 进一步显示到浏览器地址栏里.(不就被被别人看到看吗)
        // 相比之下, POST 则是在body中,不会在界面上显示出来,所以就更安全了) , 所以这也是一个错误的说法
        // (通常说的"安全"指的是你传递的数据,不容易被黑客获取. 或者被黑客获取到之后,不容易被破解)
        // 3. GET 只能给服务器传输文本数据. POST可以给服务器传输文本 和 二进制数据  (这也是错误的说法)
        //  (1) GET 也不是不可以使用 body (body中是可以直接放二进制的)
        //   2) GET 也可以把二进制的数据进行 base64 转码, 放到 url 的 query string 中)

        // 接下来再看看另一种说法
        // 1. GET 请求是幂等的, POST请求不是幂等的. (这种说法不够准确, 但是也不是完全错)
        // (幂等这是一个数学概念, 而在计算机中你可以认为: 输入相同的内容, 输出是稳定的.)
        // (这两个具体幂不幂等, 取决于代码是怎么实现的, GET是否幂等也不是绝对的, 只不过RFC标准文档上建议GET请求实现)
        // (比如一个典型的不幂等的情况:搜狗的搜索内容,这些一定是不幂等的)
        // 2. GET请求可以被浏览器缓存 POST不可以被缓存(幂等性的延续, 如果幂等自然就可以缓存) (这个情况跟上面的幂等是一样)
        // 3.GET请求可以被浏览器收藏夹收藏, POST不能(收藏的时候可能会丢失body) (这个不能说不对,也不能说对,有的浏览器是会报错的,可以倾向于认为是对的)
        // 和技术关系不大, 和需求有关

        // *** 认识请求 "报头" (header) ***
        // Header 里的键值对是很多的. 主要是挑几个重要的来讲

        // 1. Host
        // 表示服务器主机的地址和端口.
        // 2. Content-Length 和 Content-Type  (这两个存在的前提是 请求中有body,才会有这两个属性. GET请求一般就没有body)
        // Content-Length 表示 body 中的数据长度. (也是为了解决粘包问题)
        // 对于 TCP 当中的粘包问题 ,HTTP 在传输层就是基于 TCP的
        // 对于 GET 这种没有 body 的请求, 直接使用空行作为分隔符
        // 对于 POST这种有 body 的请求,就结合 空行 和 Content-Length

        // Content-Type 表示请求的 body 中的数据格式. (body中的格式,可以选择的方式是非常多的
        // 请求中 : 1. json 2. from表单的格式(相当于是把GET的query string 给搬到body中了) 3. from-data的格式 (属于是上传文件的时候要涉及到,不过也不一定)
        // 响应中 : 1. html 2.CSS 3.js 4.json 5.图片(image)....)
        // fiddler 中 紫色的表示 返回css 的 绿色的表示返回 js的
        // (html css js 是构成网页的主体  html 表示页面的骨架(页面上有什么东西) css 表示页面的样式(页面长啥样) js(表示页面的行为.(用户做什么样的操作,这边就会有什么反映)))

        // 3. User-Agent (简称 UA)
        // 表示浏览器/操作系统的属性.(描述操作系统的版本,浏览器的版本)
        // (描述了你使用什么设备上网 , (是由于时代的发展, 要用 UA中记录的浏览器版本.哪个版本的浏览器都支持哪些特性,是容易获取的,
        // (网站开发者就可以看看UA的内容来写) , 但是到现在,浏览器之间的差异就非常小了. 此时 UA的作用就没呢么关键了.
        // 现在的UA主要来区分是 PC端还是移动端))

        // 4. Referer
        // 表示这个页面是从哪个页面跳转过来的.
        // (如果是直接在地址栏输入 url 或者点击收藏夹中的按钮 这时候是都没有 Referer 的)
        // (广告主是通过Referer来统计点击数量的 , 那么是否可能存在一种情况把Referer给改了, 有!, 在2015年之前非常常见)
        // (所以就使用 HTTPS 来代替 HTTP, HTTP最大的问题在于"明文传输", 明文传输就容易被第三方篡改,
        // HTTPS 针对 HTTP数据进行了加密(header 和 body 都加密了), 通过这个手段 就可以有效遏制运行商劫持这样的情况~~)

        // 5.Cookie
        // Cookie 中存储了一个字符串, 这个数据可能是客户端(网页)自行通过 JS 写入的, 也可能来自于服务器
        // (服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据).
        // (可以认为是浏览器在本地存储的一种机制) (浏览器的数据来自于服务器)
        // (浏览器后续的操作也是要交给服务器的, 服务器这边管理了一个网站的各种核心数据)
        // (但是在运行过程中, 也会有一些数据 (如一些临时性的数据 上次登录的时间,访问时间),
        // 需要在浏览器这边存储的. 并且在后续请求的时候数据可能需要再发给服务器)
        // (存储到文件中是不可以的, 因为浏览器考虑到安全性, 禁止网页直接访问你的电脑文件系统 (防止网站中有病毒把文件删除了))
        // (为了保证安全性, 又能进行数据存储,于是就引入了Cookie (也是按照硬盘文件的方式保存的,但是浏览器把操作文件给封装了.
        // 网页只能往 Cookie 中存储键值对 (这个键值对只是简单的字符串的形式)))

        // Cookie 往往是从服务器返回的数据 (也可以是自己生成的)
        // Cookie 存储到浏览器所在主机的硬盘上. 并且是按照 域名 为维度来存储的
        // (每个域名下可以存自己的Cookie,彼此之间不影响)
        // Cookie 是按照键值对的形式来组织的. 这里的键值对也都是程序员从自定义的(和 query string差不多)
        // 后续再请求这个服务器的时候 , 就会把Cookie 中的内容自动带入到请求中,发给服务器, 服务器通过Cookie的内容做一些逻辑上的处理
        // (总的来说 Cookie 是保存了一些给程序员用的数据, 外人看不懂 (我们删除了也没事))

        //**** 认识状态码 *****
        // 状态码表示访问一个页面的结果. (是访问成功, 还是失败, 还是其他的一些情况... 以及对应的原因是什么).
        // 需要知道一些有代表性的状态码

        // 2开头的  200 ~ 207的状态码 都表示成功
        // 200 是最常见的 表示成功

        // 3 开头的  300 ~ 307的状态码 都表示重定向
        // 重定向就是 : 请求中访问的是 A 这样的地址. 响应返回了一个重定向报文, 告诉你应该要访问 B 这个地址
        // (简单就是解释 : 找别人帮忙,别人没时间, 给你介绍别人来帮你解决, 实在不行就是忙完再帮你)
        // 很多时候, 页面跳转, 就可以通过重定向来实现, 还有的时候, 某个网站, 服务器迁移了.(IP / 域名变了)
        // 就可以给旧的地址挂一个重定向响应. 访问就地址的用户就自动跳转到新的地址.
        // 最常见的就是 302 , 叫做 临时重定向  , 301 叫做永久重定向
        // (区别就是 一个是这个网站搬到其他网站之后可能会再搬回来 , 一个是搬过去之后再也不回来了)
        // 同时 重定向的响应报文中, 会带有 Location 字段 描述当前要跳转到哪个新的地址.(需要结合代码来演示)

        // 4 开头的   称之为请求错误 , 请求里面出现了一些问题
        // (客户端需要构造一个 http 请求 但是这个请求有可能不符合服务器的要求 所以就会报错)
        // 最常见的就是 404 Not Found 请求中访问的资源 , 再服务器上不存在 (表示资源不存在)
        // 403 Forbidden 表示访问的资源没有权限.
        // 405 (在写 servlet 的时候会经常看到)
        // 特殊状态码 418 I am a teapot! (杯具) 这时 HTTP RFC 文档中专门规定的一个状态码
        // 这个状态码并没有实际的意义, 只是 "开个玩笑" ,称之为 "彩蛋"


        // 5 开头的  表示服务器出错了 , 看到这个说明服务器挂了
        // 比较常见的有  500  502  503  504
        // 500 在后面自己写服务器的时候 还是比较出现的 (一般就是代码有 bug 了)

        // 一个典型的面试题 : 说一下, HTTP 状态码都有哪些常见的~~


        // 到这里 根据 HTTP 协议报文结构的基本情况基本上就结束了
        // 这里面 键值对 一定要了解
        // 里面的键值对有 1) query string  2) header 3) cookie 4) body (from key1=value1&key2=value2
        // json{key1:value1,key2:value2})  (在进行编程的时候 很多都是拿着这些键值对做文章)

        // ***** 如何让客户端构造一个HTTP请求?
        // 如何让服务器处理一个HTTP请求[重中之重] Servlet / Spring *****

        // 先说第一个问题: 客户端通常是一个浏览器: 1.直接在浏览器 地址栏 输入一个 url, 此时就构造了一个 GET 请求
        // 2. html中 一些特殊的 html 标签, 可能会触发 GET 请求.
        // (比如像 img,a,link,script)
        // 3. 通过form表单来触发 GET / POST 请求 (这个需要重点了解)
        // form 本质也是一个 HTML 标签~~

        // 接下来写一个简单的 HTML 代码, 来编写这样的一个逻辑
        // 在 d:/javaSE/frontend 文件里面
        // (HTML CSS JS 也是编程语言.他们和 C 和 Java有一个明显的差别. 这几个语言运行在浏览器上的.
        // 不像 C 需要安装 VS , 也不像 Java 需要安装 JDK. 只要有个浏览器就能运行)
        // 此处我们可以在 记事本中在 里面写内容 , 但是我们一般不推荐这样, 一般用 VS CODE 这样的前端开发工具
        // 这是一个更好的选择

        // VSCode 中不需要创建项目, 只需要打开目录即可. 在你想要编辑的目录中右键打开即可
        // 这时候会有更规范的 html 代码写法
        // html 中包含很多的标签
        // 标签往往是成对出现的(也有不成对的但标签)
        // 有开始标签和结束标签
        // 标签里面的内容(还可以嵌套其他的标签)
        // 其中<head> </head>标签里面 放的是一些属性
        // <body> </body> 标签里面放的是页面显示内容
        // html 中,都有哪些标签, 每个标签啥含义都是标准规定的

        // 运行之后我们会发现 和之前在记事本中改的效果是一样的
        // 这就涉及到 : 浏览器对于html来说具有一定的鲁棒性 (就是容错能力 (你对他越粗鲁,他表现的越棒))
        // 即使给出了一个错误的(不规范的)的html代码, 也是可以进行解析并显示的(浏览器会尽可能的进行显示)

        // 上面的标签不用一个一个的敲击, 有快捷键 输入一个 英文 ! 在回车就自动全部显示

        // <!DOCTYPE html>
        //<html lang="en">
        //<head>
        //    <meta charset="UTF-8">
        //    <meta http-equiv="X-UA-Compatible" content="IE=edge">
        //    <meta name="viewport" content="width=device-width, initial-scale=1.0">
        //    <title>Document</title>
        //</head>
        //<body>
        //
        //</body>
        //</html>

        // 当然这个功能 idea 也有

        // 接下来就具体看看form表单怎么写
        // 要用到 form标签 这里 里面会带有 action 属性
        // 开始标签中,可以写属性,属性就是一些键值对 , 可以有多个属性. 多个键值对之间使用 空格 来分割. 键和值之间使用 = 分割
        // 键不需要有引号. 值需要有双引号.
        // 此处的 action 表示的含义是 要访问请求 url 的路径是什么 (也可以带上 ip 和端口号)
        // 紧接着后面还可以有一个 method 属性
        // 描述了当前要构造的请求是 get 还是 post
        // form 只支持 get 和 post,不支持其他的http方法
        // 然后在继续往里面写
        // 写一个 input 标签 表示一个输入框
        // 一个input表示一个输入框
        // 里面可以输入字符串
        // 输入框中的内容就会被构造成 http 请求中的 query string
        // (query string 是键值对. 其中key 就是 input 输入框的 name 属性, value 就是输入框中用户输入的内容)
        //  (key 就是 input 标签后面的name 属性)

        // 光有这个还不够用
        // 往往还需要有一个提交按钮
        /*
        <input type="text" name="key1">
        <input type="text" name="key2">
        <input type="text" name="key3">
        <input type="submit" name="提交">
         */
        // value 里的内同就是按钮上显示的文本,自己想叫啥就起什么名字
        // 只有设定成 这样的 type="submit" 类型 才会是一个提交内容
        // 当前已经吧请求构造出来了. 很明显,当前得到的响应是 404. 要想有一个正确的响应, 往往需要服务器这边的配合

        // <body>
        //    <form action="http:/www.sogou.com/abc.html" method="get">
        //        <input type="text" name="key1">
        //        <input type="text" name="key2">
        //        <input type="text" name="key3">
        //        <input type="submit" name="提交">
        //    </form>
        //</body>

        // 4. ajax的方式
        // (form是有一点缺陷的 orm 只支持 get 和 post,不支持其他的http方法 , 而且还会触发页面跳转(但是有的时候我们不像跳转)
        // ) 所以就提供了 ajax. 通过 js 提供的 api 来构造 http请求. 针对拿到的响应, 同样可以使用js 灵活处理.想要怎么处理都行.
        // 或者想跳转不跳转都行
        // 这样给前端代码 带来了更多的可操作空间
        // 现在的网站,主体都是通过 ajax  的方式来进行交互的

        // 浏览器原生提供了ajax 的 qpi , 原生的 api 特别难用.
        // 还有一些第三方库,封装了 ajax. 就准备使用封装的版本来进行操作.我这里使用的是 jquery 这个库,封装ajax
        // jquery 是属于前端领域非常知名的库 (但是是曾经的王者)
        // 现在的前端出来了三大框架 (Anglar , React , Vue)

        // 在创建一个新的文件, 然后
        // 1.引入jquery这个库 (作为第三方库,是需要额外下载引入的)
        // 前端引入第三方库非常容易的.只要代码中写一个库的地址即可.
        // (搜索 jquery cdn 然后在里面 复制 https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js 这个连接(在下面找))

        // js 和java之间还是有一点差别的.差别也不是很大, 主要体现在类型(如 int char...)系统上
        // 基本的 变量定义,运算符,表达式,条件,循环,函数....大同小异

        // <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
        //    <script>
        //         // let value1 = '1'; // 这个写法就是定义变量,不需要写类型, 不管是啥类型 都是 let
        //          // 变量具体类型是根据 = 后面初始化的值的类型来确定的
        //          // 此处的 '1' 是一个字符串, value1变量类型也就是字符串了
        //
        //          //  写成post的形式的lest
        //          /* let body = {
        //              key1:1,
        //              key2:2
        //             }
        //
        //        // 这里面编写自己的 js 代码
        //        $.ajax({
        //            //type:'get',
        //
        //
        //            // 改成 post 的版本
        //             /*
        //               type:'post',
        //                contentType: 'application/json',
        //                data: JSON.stringify(body), // 这个操作可以把 js 对象 转成 json 格式的字符串
        //               */
        //          //  url:'https://www.sogou.com/abc.html?' + 'key1=' + value1, // 顺便构造 query string
        //            url:'https://www.sogou.com/abc.html',
        //            success: function(body){
        //                   console.log(body); // 打印这个body
        //            }
        //        });
        //        //$是一个变量名 是一个全局变量, 在 jquery 中定义的 ,
        //        // 通过这个变量来调用一些方法,来使用jquery 的 api
        //        // 在js中 {}表示 对象, {} 里面使用键值对的方式来描述属性名和属性值
        //    </script>

        // 在js中对象属性的值 也可以是一个函数
        // 这个函数也可以是一个匿名函数 也就是相当于一个 lambda 表达式
        // 不需要写返回类型
        // (也可以自己定义一个函数然后传入到 success 中,但是我们一般不这样写,而是直接把函数定义在这里面)
        // success 这个函数,不是立即执行的. 而是服务器返回 200这样的响应的时候,才会执行到 success
        // success 执行的时机不是程序员自己能控制的
        // 而是在合适的时候自动被调用, 这样的函数称为 "回调函数".

        // 此处success: function(body) 这个body 这个形参就是 http 的响应的body内容
        // 上面的VSCode的代码就是 包含 get请求和 post请求这两个

        // 有时候,获取get请求和post请求 还需要更简单,更方便的方式. 第三方工具(图形化界面构造), 来实现这里的效果
        // 这里最主要使用的是 postman (会用,很简单的)
        // (一般用于测试阶段)

        //******* HTTPS *******
        // 当前网络上, 主要都是 HTTPS 了 , 很少见到 HTTP
        // 实际上 HTTPS 也是 基于 HTTP, 只不过HTTPS 在HTTP 的基础之上 引入了"加密"机制

        // HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在传输过程中出现一些被篡改的情况.
        // 臭名昭著的 "运营商劫持"

        // ****  "加密" 是什么 ****
        // 加密就是把 明文 (要传输的信息)进行一系列变换, 生成 密文 .
        // 解密就是把 密文 再进行一系列变换, 还原成 明文 .
        // 在这个加密和解密的过程中, 往往需要一个或者多个中间的数据, 辅助进行这个过程, 这样的数据称为 密
        //钥 (正确发音 yue 四声, 不过大家平时都读作 yao 四声) .

        //加密解密到如今已经发展成一个独立的学科: 密码学.

        // 在密码学中, 使用密钥加密,有两种方式
        // 1. 对称加密. 加密和解密,使用的密钥是同一个密钥
        // 2. 非对称加密 , 有两个密钥(构成一对) , 一个称为 公钥  ; 一个称为 私钥
        // 公钥就是可以公开的, 私钥就是自己藏好的 (明文 + 公钥 => 密文 ; 密文 + 私钥 => 明文. 当然也可以反过来)
        // 用一个钥匙加密,就用另一个钥匙解密

        // ***** HTTPS的工作过程 *****
        // 目标就是针对 HTTP 这里的 header 和 body 进行加密 ~~

        // 1. 先引入对称加密~~
        // 看看下面的模型:
        // (客户端[加密(明文请求, 密钥 => 密文请求)])  ---- 密文请求 ---> [黑客入侵了路由器截获了请求内容] ----密文请求 ---->(服务器[解密(密文请求,密钥 => 明文请求)])
        // 客户端使用密钥进行对称加密                                                 |                         服务器拿着同一个密钥进行解密
        //                                                      (由于黑客手里没有密钥黑客无法获取加密之前的内容)
        //   所以这里的传输就是 比较安全 的了

        // 但是上面的问题存在一个重要的问题. 服务器不只是和一个客户端通信,而是有很多的客户端进行通信
        // 这些客户端使用的 对称密钥 是相同的么?
        // 很明显,必须要求每个客户端的密钥都不相同, 彼此之间才不知道对方的密钥是什么
        // 呢么就需要在每个客户端和服务器建立连接的时候,就把密钥生成出来(涉及到一些随机数机制在里面, 保证每个客户生成的密钥不同)
        // 客户端再把自己的密钥通过 网络传输 给服务器
        // 但是如果在进行网络传输中间密钥被黑客截获了,那不就凉了
        // 所以这也就衍生出来另一个问题 : 此时的加密过程就车型如虚设
        // 所以这就需要 针对密钥 进行 加密
        // 而不是再搞一个密钥经行密钥加密 , 无论引入多少个密钥都有泄露风险~~

        // 所以为了解决上述安全传输密钥的问题,那就是
        // 2. 非对称加密
        //  客户端     --------   被黑客入侵的网络设备 --------- 服务器
        // 服务器生成一对公钥和私钥 , 公钥返回给客户端 , 私钥则自己保留
        // 此时黑客也可能拿到公钥, 不过不要紧
        // 客户端仍然生成对称密钥使用服务器的公钥 对对称密钥进行加密 , 得到了密钥的密文
        // 发送给服务器
        // 此时如果黑客拿到加密后的 对称密钥是无能为力的 , 公钥 加密需要私钥解密.
        // 而私钥只有 服务器 才有. 黑客没有

        // 呢么既然有了非对称加密 为什么还要有对称加密呢
        // 因为 非对称加密/解密 运算成本是比较高的 . 运算速度也是比较低的.
        // 对称加密, 运算成本低, 速度快

        // 使用 非对称加密, 只是用来进行关键环节 (传输密钥)(一次性工作,体积也不大) , 成本可控

        // 但是光靠以上这些还是不够的.仍然有一个严重的漏洞,如果黑客利用好这个漏洞,仍然可以获取到原始的明文数据
        // 一下面模型举例:
        // 客户端 ------- 询问公钥  ------> 黑客入侵的设备  ------询问公钥 ------> 服务器(提前生成好公钥pub1 和 私钥pri1)
        // 客户端 <------- 黑客生成的公钥 pub2  ----- 黑客入侵的设备 (公钥 pub2 私钥 pri1)  <----- 返回 pub1 ----- 服务器
        // 客户端不知道 pub2 是黑客的, 所以就 使用 pub2 针对对称密钥进行加密
        // 客户端 ----- 加密对称密钥(基于pub2) ----> 黑客入侵的设备 --------- 加密对称密钥(基于pub1) ----> 服务器
        //                                   黑客收到密钥后进行解密,就拿到了原始的对称密钥
        //                                   并使用服务器刚才的pub1,重新进行加密,进一步发给服务器(为了就是瞒天过海)
        // 服务器收到之后,使用pri1进行解密,这个解密完全是能成功的 , 于是服务器也受到了对称密钥
        // 客户端 <------ 好的,就是用这个密钥  ----- 黑客入侵的服务器 <----- 好的,就是用这个密钥 ---- 服务器
        // 由于对称密钥黑客在刚才的过程中, 已经拿到, 那么今后在进行传输数据的之后,对于黑客来说就是一览无余了

        // 那么如何解决上述问题呢?
        // 上述问题存在的关键就是 , 客户端拿到的密钥并不知道是不是黑客伪造的, 所以这是破局的关键
        //
        // ******* 引入第三方的可以被大家都信任的公共机构 *******
        // 在非对称加密中 开发人员在搭建服务器的时候 只需要生成好一对公钥私钥就好了, 不同的客户端都要用同一份公钥,这里和对称加密是不同的

        // ***** 引入证书 *****
        // 在客户端和服务器刚一建立连接的时候, 服务器给客户端返回一个 证书.这个证书包含了刚才的公钥, 也包含了网站的身份信息.

        // 这个 证书 可以理解成是一个结构化的字符串, 里面包含了以下信息:
        //证书发布机构
        //证书有效期
        //公钥
        //证书所有者
        //数字签名
        //......
        // 当客户端获取到这个证书之后, 会直接先对证书进行校验(防止证书是伪造的). (而不是先询问公钥了)
        //  判定证书的有效期是否过期
        //  判定证书的发布机构是否受信任(操作系统中已内置的受信任的证书发布机构).
        //  验证证书是否被篡改: 从系统中拿到该证书发布机构的公钥, 对签名解密, 得到一个 hash 值(称为数
        //  据摘要), 设为 hash1. 然后计算整个证书的 hash 值, 设为 hash2. 对比 hash1 和 hash2 是否相等.
        //  如果相等, 则说明证书是没有被篡改过的 (这就是数字签名 => 本质上就是被加密的校验和) (这个过程就成为 证书校验)
        // (颁发证书的时候, 公证机构 就会针对证书中的各个属性, 计算出一个校验和, 并且针对这个校验和进行加密,就可以得到了数字签名)
        // (这个加密,也是非对称加密.公证机构,自己生成一对公钥和私钥(和服务器的公钥私钥还不一样), 公证机构就会给自己持有私钥,公钥就会发送到各个客户端设备
        // (往往公钥都是内置到系统中的,安装了操作系统,就会自带公证机构的公钥)) (公证就会使用自己的私钥对校验和进行加密,得到数字签名)
        // 此时客户端拿到数字签名,就会通过系统内置的 公证机构的公钥,进行解密了,得到最初的校验和 , 客户端再重新计算一边这里面的校验和
        // 和解密出来的校验和进行对比, 如果校验和一直,就可以认为证书没有被篡改过, 公钥就是可信的(服务器原始的公钥)


        // 总结
        // HTTPS 工作过程中涉及到的密钥有三组.
        // 第一组(非对称加密): 用于校验证书是否被篡改. 服务器持有私钥(私钥在注册证书时获得), 客户端持有公
        // 钥(操作系统包含了可信任的 CA 认证机构有哪些, 同时持有对应的公钥).  服务器使用这个私钥对证书的
        // 签名进行加密. 客户端通过这个公钥解密获取到证书的签名, 从而校验证书内容是否是篡改过.
        // (对称加密, 加密业务数据)

        // 第二组(非对称加密): 用于协商生成对称加密的密钥. 服务器生成这组 私钥-公钥 对, 然后通过证书把公钥
        // 传递给客户端. 然后客户端用这个公钥给生成的对称加密的密钥加密, 传输给服务器, 服务器通过私钥解
        // 密获取到对称加密密钥.
        // (非对称加密, 加密对称密钥)

        // 第三组 中间人攻击

        // 第四组(对称加密): 客户端和服务器后续传输的数据都通过这个对称密钥加密解密.
        // (使用证书, 校验服务器的公钥)

        // 这三者相结合, 保证最终 https 的安全性了
        // *********** 这是一个经典的面试题 ************
    }
}